﻿
using Xacml.Core;
using Xacml.Core.Interfaces;
using System;
using System.Collections;
using System.Xml;

namespace Xacml.Core.Policy
{
  public class PolicySetElementReadWrite : XacmlElement, IHasTarget
  {
    private ObligationCollectionReadWrite _obligations = new ObligationCollectionReadWrite();
    private string _id = string.Empty;
    private string _description = string.Empty;
    private ArrayList _policies = new ArrayList();
    private ArrayList _combinerParameters = new ArrayList();
    private ArrayList _policyCombinerParameters = new ArrayList();
    private ArrayList _policySetCombinerParameters = new ArrayList();
    private string _xpathVersion = string.Empty;
    private string _policyCombiningAlgorithm;
    private TargetElementReadWrite _target;

    public virtual string Id
    {
      get
      {
        return this._id;
      }
      set
      {
        this._id = value;
      }
    }

    public virtual string Description
    {
      get
      {
        return this._description;
      }
      set
      {
        this._description = value;
      }
    }

    public virtual string PolicyCombiningAlgorithm
    {
      get
      {
        return this._policyCombiningAlgorithm;
      }
      set
      {
        this._policyCombiningAlgorithm = value;
      }
    }

    public virtual ObligationCollectionReadWrite Obligations
    {
      get
      {
        return this._obligations;
      }
      set
      {
        this._obligations = value;
      }
    }

    public virtual TargetElementReadWrite Target
    {
      get
      {
        return this._target;
      }
      set
      {
        this._target = value;
      }
    }

    public virtual ArrayList Policies
    {
      get
      {
        return this._policies;
      }
      set
      {
        this._policies = value;
      }
    }

    public virtual string XPathVersion
    {
      get
      {
        return this._xpathVersion;
      }
      set
      {
        this._xpathVersion = value;
      }
    }

    public override bool IsReadOnly
    {
      get
      {
        return false;
      }
    }

    public PolicySetElementReadWrite(string id, string description, TargetElementReadWrite target, ArrayList policies, string policyCombiningAlgorithm, ObligationCollectionReadWrite obligations, string xpathVersion, XacmlVersion schemaVersion)
      : base(XacmlSchema.Policy, schemaVersion)
    {
      this._id = id;
      this._description = description;
      this._target = target;
      this._policies = policies;
      this._policyCombiningAlgorithm = policyCombiningAlgorithm;
      this._obligations = obligations;
      this._xpathVersion = xpathVersion;
    }

    public PolicySetElementReadWrite(XmlReader reader, XacmlVersion schemaVersion)
      : base(XacmlSchema.Policy, schemaVersion)
    {
      if (reader.LocalName == "PolicySet" && this.ValidateSchema(reader, schemaVersion))
      {
        this._id = reader.GetAttribute("PolicySetId");
        this._policyCombiningAlgorithm = reader.GetAttribute("PolicyCombiningAlgId");
        while (reader.Read())
        {
          switch (reader.LocalName)
          {
            case "Description":
              this._description = reader.ReadElementString();
              break;
            case "PolicySetDefaults":
              if (reader.Read() && reader.Read())
              {
                if (reader.LocalName == "XPathVersion" && this.ValidateSchema(reader, schemaVersion))
                {
                  this._xpathVersion = reader.ReadElementString();
                  if (this._xpathVersion != null && this._xpathVersion.Length != 0 && this._xpathVersion != "http://www.w3.org/TR/1999/Rec-xpath-19991116")
                    throw new Exception(Resource.ResourceManager[Resource.MessageKey.exc_unsupported_xpath_version, new object[1]
                    {
                      (object) this._xpathVersion
                    }]);
                }
                reader.Read();
                break;
              }
              break;
            case "Target":
              this._target = new TargetElementReadWrite(reader, schemaVersion);
              break;
            case "PolicySet":
              if (!reader.IsEmptyElement && reader.NodeType != XmlNodeType.EndElement)
              {
                this._policies.Add((object) new PolicySetElementReadWrite(reader, schemaVersion));
                break;
              }
              break;
            case "Policy":
              this._policies.Add((object) new PolicyElementReadWrite(reader, schemaVersion));
              break;
            case "PolicySetIdReference":
              this._policies.Add((object) new PolicySetIdReferenceElementReadWrite(reader, schemaVersion));
              break;
            case "PolicyIdReference":
              this._policies.Add((object) new PolicyIdReferenceElement(reader, schemaVersion));
              break;
            case "Obligations":
              while (reader.Read())
              {
                switch (reader.LocalName)
                {
                  case "Obligation":
                    this._obligations.Add(new ObligationElementReadWrite(reader, schemaVersion));
                    break;
                }
                if (reader.LocalName == "Obligations" && reader.NodeType == XmlNodeType.EndElement)
                {
                  reader.Read();
                  break;
                }
              }
              break;
            case "CombinerParameters":
              while (reader.Read())
              {
                switch (reader.LocalName)
                {
                  case "CombinerParameter":
                    this._combinerParameters.Add((object) new CombinerParameterElement(reader, schemaVersion));
                    break;
                }
                if (reader.LocalName == "CombinerParameters" && reader.NodeType == XmlNodeType.EndElement)
                {
                  reader.Read();
                  break;
                }
              }
              break;
            case "PolicyCombinerParameters":
              while (reader.Read())
              {
                switch (reader.LocalName)
                {
                  case "PolicyCombinerParameterElement":
                    this._policyCombinerParameters.Add((object) new PolicyCombinerParameterElement(reader, schemaVersion));
                    break;
                }
                if (reader.LocalName == "PolicyCombinerParameters" && reader.NodeType == XmlNodeType.EndElement)
                {
                  reader.Read();
                  break;
                }
              }
              break;
            case "PolicySetCombinerParameters":
              while (reader.Read())
              {
                switch (reader.LocalName)
                {
                  case "PolicySetCombinerParameterElement":
                    this._policySetCombinerParameters.Add((object) new PolicySetCombinerParameterElement(reader, schemaVersion));
                    break;
                }
                if (reader.LocalName == "PolicySetCombinerParameters" && reader.NodeType == XmlNodeType.EndElement)
                {
                  reader.Read();
                  break;
                }
              }
              break;
          }
          if (reader.LocalName == "PolicySet" && reader.NodeType == XmlNodeType.EndElement)
          {
            reader.Read();
            break;
          }
        }
      }
      else
        throw new Exception(Resource.ResourceManager[Resource.MessageKey.exc_invalid_node_name, new object[1]
        {
          (object) reader.LocalName
        }]);
    }

    public void WriteDocument(XmlWriter writer, Hashtable namespaces)
    {
      writer.WriteStartElement("PolicySet");
      foreach (DictionaryEntry dictionaryEntry in namespaces)
        writer.WriteAttributeString("xmlns", dictionaryEntry.Key.ToString(), (string) null, dictionaryEntry.Value.ToString());
      writer.WriteAttributeString("PolicySetId", this._id);
      writer.WriteAttributeString("PolicyCombiningAlgId", this._policyCombiningAlgorithm);
      if (this._description != string.Empty)
        writer.WriteElementString("Description", this._description);
      if (this._xpathVersion != string.Empty)
      {
        writer.WriteStartElement("PolicySetDefaults");
        writer.WriteElementString("XPathVersion", this._xpathVersion);
        writer.WriteEndElement();
      }
      if (this._target != null)
        this._target.WriteDocument(writer);
      foreach (object obj in this._policies)
      {
        if (obj is PolicyElementReadWrite)
          ((PolicyElementReadWrite) obj).WriteDocument(writer);
        else if (obj is PolicySetElementReadWrite)
          ((PolicySetElementReadWrite) obj).WriteDocument(writer);
        else if (obj is PolicyIdReferenceElementReadWrite)
          ((PolicyIdReferenceElementReadWrite) obj).WriteDocument(writer);
        else if (obj is PolicySetIdReferenceElementReadWrite)
          ((PolicySetIdReferenceElementReadWrite) obj).WriteDocument(writer);
      }
      if (this._obligations != null)
        this._obligations.WriteDocument(writer);
      writer.WriteEndElement();
    }

    public void WriteDocument(XmlWriter writer)
    {
      writer.WriteStartElement("PolicySet");
      writer.WriteAttributeString("PolicySetId", this._id);
      writer.WriteAttributeString("PolicyCombiningAlgId", this._policyCombiningAlgorithm);
      if (this._description != string.Empty)
        writer.WriteElementString("Description", this._description);
      if (this._xpathVersion != string.Empty)
      {
        writer.WriteStartElement("PolicySetDefaults");
        writer.WriteElementString("XPathVersion", this._xpathVersion);
        writer.WriteEndElement();
      }
      this._target.WriteDocument(writer);
      foreach (object obj in this._policies)
      {
        if (obj is PolicyElementReadWrite)
          ((PolicyElementReadWrite) obj).WriteDocument(writer);
        else if (obj is PolicySetElementReadWrite)
          ((PolicySetElementReadWrite) obj).WriteDocument(writer);
        else if (obj is PolicyIdReferenceElementReadWrite)
          ((PolicyIdReferenceElementReadWrite) obj).WriteDocument(writer);
        else if (obj is PolicySetIdReferenceElementReadWrite)
          ((PolicySetIdReferenceElementReadWrite) obj).WriteDocument(writer);
      }
      this._obligations.WriteDocument(writer);
      writer.WriteEndElement();
    }
  }
}
